#include <rtthread.h>
#include <stdio.h>

#include "../serial/rttSerial.h"
#include "../adapter/rttJtagGPIO.h"

#ifndef RBB_SERIAL_NAME
#define RBB_SERIAL_NAME ":dev/uart2"
#endif
#ifndef RBB_PINS_NAME
#define RBB_PINS_NAME "tdi:pb9,tms:pa8,tck:pc6,tdo:pd14,srs:pd12"
#endif

static int process_remote_protocol(rttJtagGPIO &jtag, int c)
{
    int ret = 0;

    if (c == -1 || c == 'Q') /* Quit */
        return c;

    if (c == 'b' || c == 'B') /* Blink */
    {
        c = c - 'b';
        jtag.blink(!!(c));
    }
    else if (c >= 'r' && c <= 'r' + 3)
    { /* Reset */
        char d = c - 'r';
        jtag.reset(!!(d & 2), (d & 1));         
    }
    else if (c >= '0' && c <= '0' + 7)
    { /* Write */
        char d = c - '0';
        jtag.ttt_write(!!(d & 4), !!(d & 2), (d & 1));    
    }
    else if (c == 'R')
    {
        ret = jtag.tdo_read() + '0';
    }
    else
    {
        printf("Unknown command '%c' received", c);
    }

    return ret;
}

static void rbb_thread(void *p)
{
    rttJtagGPIO jtag;
    mopenocd::rttSerial ser;
    char ch;
    int ret;

    if (!jtag.open(RBB_PINS_NAME))
    {
        printf("fail open: %s\n", RBB_PINS_NAME);
        return;
    }

    if (!ser.open(RBB_SERIAL_NAME))
    {
        printf("fail open: %s\n", RBB_SERIAL_NAME);
        return;
    }

    ser.setBaudRate(115200);

    while (1)
    {
        ret = ser.read(&ch, 1);
        if (ret != 1)
        {
            continue;
        }

        ret = process_remote_protocol(jtag, ch);
        if (ret == '0' || ret == '1')
        {
            ch = (char)ret;
            ser.write(&ch, 1);
        }
    }
}

static int rbb_init(void)
{
    rt_thread_t t;

    t = rt_thread_create("rbb", rbb_thread, 0, 4096, 20, 20);
    if (t)
        rt_thread_startup(t);

    return 0;
}
INIT_APP_EXPORT(rbb_init);

#if 0
static int rbbstest(int ac, char **av)
{
    mopenocd::rttSerial ser;
    char ch[32];
    int ret;
    int cnt = 10000;

    if (!ser.open(RBB_SERIAL_NAME))
    {
        printf("fail open: %s\n", RBB_SERIAL_NAME);
        return;
    }

    ser.setBaudRate(115200);

    while (cnt -- > 0)
    {
        ret = ser.readAll(ch, 32, 1000);
        if (ret <= 0)
        {
            continue;
        }

        ser.write(ch, ret);
    }

    return 0;
}
MSH_CMD_EXPORT(rbbstest, serial test Rx and Tx);
#endif
